package cn.yunyichina.provider.clinic.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.yunyichina.provider.framework.dubbo.service.MessageService;
import cn.yunyichina.utils.log.Log;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import cn.yunyichina.provider.clinic.constant.CacheConstant;
import cn.yunyichina.provider.clinic.dao.ClinicRecordDao;
import cn.yunyichina.provider.clinic.hisiface.vo.ClinicVo;
import cn.yunyichina.provider.clinic.manager.ClinicBizManager;
import cn.yunyichina.provider.clinic.others.hisiface.MZFeeDetail;
import cn.yunyichina.provider.clinic.thread.QueryAndSaveMzDetailRunnable;
import cn.yunyichina.provider.clinic.vo.ListMzfeeOutVoRequest;
import cn.yunyichina.provider.clinic.vo.ListMzfeeOutVoResponse;
import cn.yunyichina.provider.clinic.vo.ListMzfeeVoResponse;
import cn.yunyichina.provider.framework.annotation.validate.ValidateException;
import cn.yunyichina.provider.framework.annotation.validate.Validator;
import cn.yunyichina.provider.framework.common.PKGenerator;
import cn.yunyichina.provider.framework.data.SpringContextHandler;
import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.CacheService;
import cn.yunyichina.provider.framework.dubbo.service.HisifaceService;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.base.Org;
import cn.yunyichina.provider.iface.entity.base.OrgSetting;
import cn.yunyichina.provider.iface.entity.cache.SessionInfo;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.common.TestFlag;
import cn.yunyichina.provider.iface.entity.hisiface.base.PatientVo;
import cn.yunyichina.provider.iface.entity.hisiface.base.PatientVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.AckClinicPayVo;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.AckClinicPayVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.ClinicInsuranceVo;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.ClinicInsuranceVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.ClinicPrePriceVo;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.ClinicPrePriceVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.FeeDetailVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.FeeVo;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.FeeVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.PrescriptionUploadVo;
import cn.yunyichina.provider.iface.entity.hisiface.clinic.PrescriptionUploadVoResponse;
import cn.yunyichina.utils.commons.DateUtils;
import cn.yunyichina.utils.convert.JsonUtils;
import cn.yunyichina.utils.convert.ObjectParser;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

@Service
public class MzfeeServiceImpl {

    private Logger logger = LoggerFactory.getLogger(MzfeeServiceImpl.class);

    @Autowired
    private ClinicRecordDao clinicRecordDao;

    private final static int MAX_THREAD_COUNT = 13;

    /**
     * 门诊待缴费明细查询 - yyt.clinic.mzfee.detail.get
     */
    public Response getMzfeeDetail(String json, String sessionId) {
        JSONObject jsonObj = JSONObject.parseObject(json);
        String mzFeeId = jsonObj.getString("mz_fee_id");
        String mzFeeInfoJson = CacheService.getGlobalKey(CacheConstant.CACHE_CLINIC_MODULE,
                CacheConstant.CACHE_REGION_MZ_FEE_INFO, mzFeeId);
        logger.info("门诊待缴费明细查询, mzFeeInfoJson=" + mzFeeInfoJson);
        ListMzfeeVoResponse mzFee = JsonUtils.parseObject(mzFeeInfoJson, ListMzfeeVoResponse.class);

        Map<String, Object> resultMap = new HashMap<String, Object>();

        String userInfoJson = CacheService.getSessionKey(sessionId, CacheConstant.CACHE_SESSION_USER);
        SessionInfo userInfo = JsonUtils.parseObject(userInfoJson, SessionInfo.class);

        ClinicBizManager clinicBizManager = (ClinicBizManager) SpringContextHandler.getBean("clinicBizManager");
        List<FeeDetailVoResponse> list = clinicBizManager.getMZFeeDetail(mzFee, userInfo, sessionId);
        MZFeeDetail data = new MZFeeDetail();
        if (list.size() > 0) {
            resultMap.put("list", list);
        } else {
            List<MZFeeDetail> list2 = new ArrayList<MZFeeDetail>();
            list2.add(data);
            resultMap.put("list", list2);
        }

        return new Response("0", "", JSON.toJSONString(resultMap));
    }

    /**
     * 待缴费查询-外部接口 yyt.clinic.mzfee.out.list
     *
     * @param data
     * @param sessionId
     * @return
     */
    @Transactional
    public Response listMzfeeOut(String data, String sessionId, String appId) throws Exception {
        Response response = new Response();
        logger.info("待缴费查询外部接口, 方法入参data=" + data);

        // 转换成-->RequestVo
        ListMzfeeOutVoRequest requestVo = JsonUtils.parseObject(data, ListMzfeeOutVoRequest.class);

        // 校验RequestVo的数据h
        try {
            Validator.getInstance().validate(requestVo);
        } catch (ValidateException ex) {
            logger.info("待缴费查询外部接口, 数据校验失败:" + ex.getMessage() + " | 方法入参:" + data + "！");
            logger.error("error", ex);
            response.setResultCodeAndMessage("3001", "数据校验失败:" + ex.getMessage() + "！");
            return response;
        }

        // 调用患者信息查询 getPatient，如果是
        // 电脑号-转换成-->就诊卡号，如果是就诊卡号，则直接查询
        PatientVo patientvo = new PatientVo();
        patientvo.setBranchCode(requestVo.getBranchCode());
        patientvo.setHospitalCode(requestVo.getHospitalCode());
        patientvo.setPatCardNo(requestVo.getPatCardNo());
        patientvo.setPatCardType(String.valueOf(requestVo.getPatCardType()));
        patientvo.setSessionId(sessionId);
        patientvo.setPatName(requestVo.getPatName());
        Map<String, Object> extMap = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(requestVo.getSocialSecurityNo())) {
            extMap.put("security_no", requestVo.getSocialSecurityNo());
        }
        extMap.put("pat_mobile",requestVo.getPatMobile()==null?"":requestVo.getPatMobile());
        extMap.put("pat_sex",requestVo.getPatSex()==null?"":requestVo.getPatSex());
        extMap.put("guard_name","");
        extMap.put("guard_id_no","");

        patientvo.setExtendParams(JsonUtils.toJsonString(extMap));

        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调hisiface模块, 查询患者信息入参request="
                + JSON.toJSONString(patientvo));
        ResCommon<PatientVoResponse> patientResponse = HisifaceService.getHisifaceClient().getPatient(patientvo);
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调hisiface模块, 查询患者信息返回response="
                + JSONObject.toJSONString(patientResponse));
        if (!"0".equals(patientResponse.getResultCode())) {
            response.setResultCodeAndMessage("3000", "查询患者信息失败:" + patientResponse.getResultMessage() + "！");
            return response;
        }
        PatientVoResponse patientInfo = JsonUtils.parseObject(patientResponse.getResult(), PatientVoResponse.class);
        if (StringUtils.isBlank(patientInfo.getPatCardNo())) {
            response.setResultCodeAndMessage("3000", "查询患者信息失败，无卡号返回！");
            return response;
        }
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 查询患者信息返回结构体中, 结果内容result="
                + JSON.toJSONString(patientResponse.getResult()));

        // 根据查询出来患者的就诊卡号，调用查询待缴费列表
        FeeVo feevo = new FeeVo();
        feevo.setHospitalCode(requestVo.getHospitalCode());
        feevo.setBranchCode(requestVo.getBranchCode());
        feevo.setPatCardNo(patientInfo.getPatCardNo());
        feevo.setPatCardType("1");
        feevo.setMzFeeId(requestVo.getMzFeeId());
        feevo.setRecipeType(requestVo.getRecipeType());
        feevo.setSessionId(sessionId);
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调hisiface模块, 门诊待缴费记录查询接口入参request="
                + JSON.toJSONString(feevo));
        ResCommon<List<FeeVoResponse>> feeResponse = HisifaceService.getHisifaceClient().listClinicFee(feevo);
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调hisiface模块, 门诊待缴费记录查询接口返回response="
                + JSONObject.toJSONString(feeResponse));
        if (!ResCommon.SUCCESS_CODE.equals(feeResponse.getResultCode())) {
            response.setResultCodeAndMessage("3000", StringUtils.isBlank(feeResponse.getResultMessage())?
                    "查询就诊卡号" + patientInfo.getPatCardNo() + "对应的待缴费列表失败！":feeResponse.getResultMessage());
            return response;
        }
        List<FeeVoResponse> feeVoResponses = JsonUtils.parseObject(feeResponse.getResult(), List.class);
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 门诊待缴费记录查询接口返回结构体中, 结果内容result="
                + JSON.toJSONString(feeVoResponses));
        if (CollectionUtils.isEmpty(feeVoResponses)) {
            response.setResultCodeAndMessage("3002", "不存在待缴费记录！");
            return response;
        }

        // 查询医院信息 需要产出hospitalId hospitalName branchId branchCode
        String hospitalCode = requestVo.getHospitalCode();
        String branchCode = requestVo.getBranchCode();
        String hospitalAppCode = requestVo.getHospitalAppCode();// 医院应用编码

        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("org_code", hospitalCode);
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调base模块, 查询医院信息入参request="
                + JSON.toJSONString(paramMap));
        Response response1 = BaseService.callUnderlineFromInternal("yyt.base.branchhospital.org.list",
                JSON.toJSONString(paramMap));
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调base模块, 查询医院信息返回response="
                + JSONObject.toJSONString(response1));
        if (!"0".equals(response1.getResultCode())) {
            response.setResultCodeAndMessage("3000", "没有org_code对应的机构信息！");
            return response;
        }
        List<Org> orgList = JsonUtils.parseArray(response1.getResult(), Org.class);
        if (CollectionUtils.isEmpty(orgList)) {
            response.setResultCodeAndMessage("3002", "不存在[org_code:" + hospitalCode + "]对应的医院信息！");
            return response;
        }
        Org org = orgList.get(0);

        paramMap = new HashMap<String, String>();
        paramMap.put("org_id", org.getId());
        paramMap.put("his_code", branchCode);
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调base模块, 查询医院信息配置列表入参request="
                + JSON.toJSONString(paramMap));
        response1 = BaseService.callUnderlineFromInternal("yyt.base.branchhospital.setting.list",
                JSON.toJSONString(paramMap));
        logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调base模块, 查询医院信息配置列表返回response="
                + JSON.toJSONString(response1));
        if (!"0".equals(response1.getResultCode())) {
            response.setResultCodeAndMessage("3003", "没有his_code对应的设置:" + response1.getResultMessage() + "！");
            return response;
        }
        List<OrgSetting> OrgHospitalSettingList = JsonUtils.parseArray(response1.getResult(), OrgSetting.class);
        if (CollectionUtils.isEmpty(OrgHospitalSettingList)) {
            response.setResultCodeAndMessage("3004", "不存在[his_code:" + hospitalCode + "]对应的设置信息！");
            return response;
        }
        OrgSetting setting = OrgHospitalSettingList.get(0);

        String hospitalId = org.getId();
        String hospitalName = org.getOrgName();
        String branchId = setting.getBranchId();

        // 循环所有待缴费记录
        // 对需要可做医保结算的门诊单做医保预结算
        List<OrderExtVo> orders = new ArrayList<OrderExtVo>();
        for (int i = 0; i < feeVoResponses.size(); i++) {
            FeeVoResponse mzfee = new FeeVoResponse();
            FeeVoResponse mzfeeTmp = JsonUtils.parseObject(JSON.toJSONString(feeVoResponses.get(i)),
                    FeeVoResponse.class);
            BeanUtils.copyProperties(mzfeeTmp, mzfee);
            logger.info("待缴费查询外部接口 mzfee=" + JSONObject.toJSONString(mzfee));

            OrderExtVo order = new OrderExtVo();
            if (StringUtils.isNotBlank(requestVo.getPromoterId())) {
                order.setPromoterId(requestVo.getPromoterId());
            }
            order.setOpenId(requestVo.getOpenId());
            order.setId(PKGenerator.generateId());
            // 空或0为海鹚，1为新平台，2为云医宝
            if(StringUtils.isNotBlank(mzfee.getCanBuyOut()) && "1".equals(mzfee.getCanBuyOut())){
                // 外购处方单
                order.setOrderNo(CacheService.generateOrderNum(10, 6));
            }else if (requestVo.getIsFromInner() != null && 1 == requestVo.getIsFromInner().intValue()) {
                // 新平台订单YPA
                order.setOrderNo(CacheService.generateOrderNum(2, 3));
            } else if (requestVo.getIsFromInner() != null && 2 == requestVo.getIsFromInner().intValue()) {
                // 云医宝 
                order.setOrderNo(CacheService.generateOrderNum(2, 3));
            } else {
                // 其他都为YCP
                order.setOrderNo(CacheService.generateOrderNum(2, 1));
            }

            order.setOrgCode(hospitalCode);
            order.setBranchCode(branchCode);
            order.setOrgId(hospitalId);
            order.setOrgName(hospitalName);
            order.setOrderStatusCreate();
            order.setPayStatusAccess();
            if(StringUtils.isNotBlank(mzfee.getCanBuyOut()) && "1".equals(mzfee.getCanBuyOut())){
                // 外购处方单
                order.setOrderTypeClinicBuyOut();
            }else{
                order.setOrderTypeClinic();
            }
            order.setPayMode((short) 0);
            order.setUserId(requestVo.getUserId());
            order.setUserName(patientInfo.getPatName());
            order.setUserAddress(patientInfo.getPatAddress());
            order.setMedicalCardNo(patientInfo.getPatCardNo());
            order.setMedicalCardType(
                    patientInfo.getPatCardType() != null ? Short.parseShort(patientInfo.getPatCardType()) : (short) 1);
            order.setPayUserId("");
            order.setIdCardNo(patientInfo.getPatIdNo());
            order.setIdCardType(
                    StringUtils.isNotBlank(patientInfo.getPatIdType()) ? Short.parseShort(patientInfo.getPatIdType()) : (short) 1);
            order.setUserMobile(patientInfo.getPatMobile());
            order.setUserSex(patientInfo.getPatSex() != null ? Short.parseShort(patientInfo.getPatSex()) : (short) 3);
            order.setInsuranceCardNo(requestVo.getMedicareCardNo());
            order.setDoctorCode(mzfee.getDoctorCode());
            order.setDoctorName(mzfee.getDoctorName());
            order.setDeptCode(mzfee.getDeptCode());
            order.setDeptName(mzfee.getDeptName());
            order.setCreatedTime(DateUtils.dateToString(new Date()));
            order.setIsInsurance(mzfee.getCanUseInsurance() != null
                    ? (short) ObjectParser.toInteger(mzfee.getCanUseInsurance()).intValue() : (short) 0);
            order.setPayAmount(ObjectParser.toInteger(mzfee.getPayAmount()));
            order.setTotalAmount(ObjectParser.toInteger(mzfee.getTotalAmount()));
            order.setAccountAmount(0);
            order.setMedicareAmount(0);
            order.setInsuranceAmount(mzfee.getInsuranceAmount() != null
                    ? ObjectParser.toInteger(mzfee.getInsuranceAmount()).intValue() : 0);
            order.setMzFeeId(mzfee.getMzFeeId());

            if("gdsdermyy".equals(hospitalCode) && order.getInsuranceAmount() > 0){
                order.setInsuranceMode((short) 4);//省二判断为医保订单
            }

            Map<String, String> map = new HashMap<String, String>();
            map.put("org_app_code", appId);
            logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调base模块, 查询组织应用接口入参request="
                    + JSON.toJSONString(map));
            Response baseRes = BaseService.callUnderlineFromInternal(sessionId, "yyt.base.orgapp.get",
                    JsonUtils.toJsonString(map));
            logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调base模块, 查询组织应用接口返回response="
                    + JSON.toJSONString(baseRes));
            if ("0".equals(baseRes.getResultCode())) {
                JSONObject o = JSONObject.parseObject(baseRes.getResult());
                order.setPlatformId(o.getString("org_id"));
                // order.setPlatformName(o.getString("org_app_name"));
                order.setPlatformName(o.getString("org_name"));
                order.setPlatformOrgAppCode(o.getString("org_app_code"));// 平台应用编码
                order.setPlatformCode(o.getString("org_code"));
                order.setPlatformOrgAppName(o.getString("org_app_name"));
            }

            Map<String, String> extraParamsMap = new HashMap<String, String>();
            extraParamsMap.put("pat_card_pwd", requestVo.getPatCardPwd());
            extraParamsMap.put("his_record_time" , mzfee.getTime());
            if (12 == requestVo.getPatCardType()) {
                extraParamsMap.put("medicare_computer_no", requestVo.getPatCardNo());
            }
            extraParamsMap.put("social_security_no", requestVo.getSocialSecurityNo());
            extraParamsMap.put("social_security_type",
                    requestVo.getSocialSecurityType() != null ? String.valueOf(requestVo.getSocialSecurityType()) : "");
            extraParamsMap.put("mz_fee_id", mzfee.getMzFeeId());
            extraParamsMap.put("mz_bill_id", mzfee.getMzBillId());
            extraParamsMap.put("recipe_type", mzfee.getRecipeType());
            extraParamsMap.put("recipe_id", mzfee.getRecipeId());
            extraParamsMap.put("record_title", "门诊对外接口：" + mzfee.getDeptName() + "-" + mzfee.getDoctorName());
            extraParamsMap.put("pay_type", mzfee.getPayType() != null ? String.valueOf(mzfee.getPayType()) : "");
            extraParamsMap.put("can_buy_out",mzfee.getCanBuyOut());
            if(StringUtils.isNotBlank(mzfee.getPaid_amount())){
                extraParamsMap.put("paid_amount",mzfee.getPaid_amount());
            }

            if (requestVo.getIsFromInner() != null) {
                extraParamsMap.put("is_from_inner", String.valueOf(requestVo.getIsFromInner().intValue()));
            }
            order.setBranchId(branchId);

            // 是否新平台订单，新平台订单不需要在待缴费中查医保预结算。 海鹚、云医宝需要查预结算
            if (requestVo.getIsFromInner() == null || 1 != requestVo.getIsFromInner().intValue()) {
                // 12为社保系统中的电脑号
                if (requestVo.getPatCardType().intValue() == 12) {
                    if ("1".equals(mzfee.getCanUseInsurance())) {
                        ResCommon<ClinicInsuranceVoResponse> getClinicInsuranceResponse = null;
                        try {
                            ClinicInsuranceVo insurancevo = new ClinicInsuranceVo();
                            insurancevo.setHospitalCode(order.getOrgCode());
                            insurancevo.setBranchCode(requestVo.getBranchCode());
                            insurancevo.setPatCardNo(order.getMedicalCardNo());
                            insurancevo.setPatCardType(String.valueOf(order.getMedicalCardType()));
                            insurancevo.setMzFeeId(mzfee.getMzFeeId());
                            insurancevo.setMzBillId(mzfee.getMzBillId());
                            insurancevo.setDeptCode(order.getDeptCode());
                            insurancevo.setDoctorCode(order.getDoctorCode());
                            insurancevo.setInsuranceSource("1");
                            insurancevo.setSessionId(sessionId);
                            logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 订单号" + order.getOrderNo()
                                    + ", 调hisiface模块, 门诊医保预结算接口入参request=" + JSON.toJSONString(insurancevo));
                            getClinicInsuranceResponse = HisifaceService.getHisifaceClient()
                                    .getClinicInsurance(insurancevo);
                            logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 订单号" + order.getOrderNo()
                                    + ", 调hisiface模块, 门诊医保预结算接口返回response="
                                    + JSON.toJSONString(getClinicInsuranceResponse));
                            if (!"0".equals(getClinicInsuranceResponse.getResultCode())) {
                                response.setResultCodeAndMessage("3006", getClinicInsuranceResponse.getResultMessage());
                                return response;
                                // throw new RuntimeException("前置机返回预结算结果失败");
                            }
                            ClinicInsuranceVoResponse getClinicInsuranceVoResponse = JsonUtils.parseObject(
                                    getClinicInsuranceResponse.getResult(), ClinicInsuranceVoResponse.class);
                            order.setPayAmount(ObjectParser.toInteger(getClinicInsuranceVoResponse.getPayAmount()));
                            order.setAccountAmount(
                                    ObjectParser.toInteger(getClinicInsuranceVoResponse.getAccountAmount()));
                            order.setMedicareAmount(
                                    ObjectParser.toInteger(getClinicInsuranceVoResponse.getMedicareAmount()));
                            order.setInsuranceAmount(
                                    ObjectParser.toInteger(getClinicInsuranceVoResponse.getInsuranceAmount()));
                            order.setTotalAmount(ObjectParser.toInteger(getClinicInsuranceVoResponse.getTotalAmount()));
                            extraParamsMap.put("ss_bill_no", getClinicInsuranceVoResponse.getSsBillNo());
                            extraParamsMap.put("ss_fee_no", getClinicInsuranceVoResponse.getSsFeeNo());
                            extraParamsMap.put("cancel_bill_no", getClinicInsuranceVoResponse.getCancelBillNo());
                            extraParamsMap.put("cancel_serial_no", getClinicInsuranceVoResponse.getCancelSerialNo());
                            extraParamsMap.put("mz_category", getClinicInsuranceVoResponse.getMzCategory());
                            extraParamsMap.put("recipe_count", getClinicInsuranceVoResponse.getRecipeCount() != null
                                    ? String.valueOf(getClinicInsuranceVoResponse.getRecipeCount()) : "");
                        } catch (Exception ex) {
                            logger.error("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 订单号" + order.getOrderNo()
                                    + ", 预结算失败", ex);
                            response.setResultCodeAndMessage("3006", "预结算失败");
                            return response;
                        }
                    }
                }
                if (requestVo.getIsFromInner() != null && requestVo.getIsFromInner().intValue() == 2
                        && order.getPayAmount().intValue() != 0) {
                    if ("true".equals(TestFlag.TEST_FLAG)) {
                        extraParamsMap.put("yyt_qrcode",
                                "http://testpay.yunyichina.cn/paysdk/general.html?order_no=" + order.getOrderNo()
                                        + "&app_code=" + appId + "&org_code=" + hospitalCode
                                        + "&topic=YYB_CLINIC&return_url=&timeout_express=");
                    } else {
                        extraParamsMap.put("yyt_qrcode",
                                "http://pay.yunyichina.cn/paysdk/general.html?order_no=" + order.getOrderNo()
                                        + "&app_code=" + appId + "&org_code=" + hospitalCode
                                        + "&topic=YYB_CLINIC&return_url=&timeout_express=");
                    }
                } else {
                    if ("true".equals(TestFlag.TEST_FLAG)) {
                        extraParamsMap.put("yyt_qrcode", "http://testpay.yunyichina.cn/paysdk/pay-clinic.html?order_no="
                                + order.getOrderNo() + "&app_code=" + appId);
                    } else {
                        extraParamsMap.put("yyt_qrcode", "http://pay.yunyichina.cn/paysdk/pay-clinic.html?order_no="
                                + order.getOrderNo() + "&app_code=" + appId);
                    }
                }
            }
            order.setExtraParams(JsonUtils.toJsonString(extraParamsMap));
            
            // 如果自费+医保金额!=总金额，直接返回异常，不产生订单。
//            if ((order.getPayAmount().intValue() + order.getInsuranceAmount().intValue()) != order.getTotalAmount()
//                    .intValue()) {
//                logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 订单号" + order.getOrderNo()
//                        + ", payAmount+insuranceAmount!=totalAmount, payAmount=" + order.getPayAmount().intValue()
//                        + ", insuranceAmount=" + order.getInsuranceAmount().intValue() + ", totalAmount="
//                        + order.getTotalAmount().intValue());
//                response.setResultCodeAndMessage("3009", "自费金额加医保金额不等于总金额。");
//                return response;
//            }

            if (StringUtils.isNotEmpty(requestVo.getMzFeeId())) {
                if (requestVo.getMzFeeId().equals(mzfee.getMzFeeId())) {
                    orders.clear();
                    orders.add(order);
                    break;
                } else {
                    continue;
                }
            }
            orders.add(order);
        }

        if (StringUtils.isNotEmpty(requestVo.getMzFeeId()) && orders.size() < 1) {
            response.setResultCodeAndMessage("3002", "mz_fee_id:" + requestVo.getMzFeeId() + "不存在待缴费记录！");
            return response;
        }

        try {
            logger.info("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调用base模块, 批量添加订单接口入参request="
                    + JSON.toJSONString(orders));
            BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.out.add", JsonUtils.toJsonString(orders));
            Thread mzDetailThread = new Thread(
                    new QueryAndSaveMzDetailRunnable(sessionId, orders, requestVo.getIsFromInner()));
            mzDetailThread.start();
        } catch (Exception ex) {
            logger.error("待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 调用base模块, 批量添加订单接口失败", ex);
            throw new CallException("3000", "listMzfeeOut-> 添加订单失败!", ex);
        }

        // 构造返回的结构
        response.setResultCodeAndMessage("0", "查询成功");
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("pat_card_type", Integer.valueOf(patientInfo.getPatCardType()));
        resultMap.put("pat_card_no", patientInfo.getPatCardNo());
        resultMap.put("pat_name", patientInfo.getPatName());
        resultMap.put("fee_list_count", orders.size());
        resultMap.put("fee_list", ListMzfeeOutVoResponse.convertClinciRecordToMzfeeOut(orders));
        response.setResult(JsonUtils.toJsonString(resultMap));
        logger.info(
                "待缴费查询外部接口, 就诊卡号" + requestVo.getPatCardNo() + ", 方法返回response=" + JSONObject.toJSONString(response));
        return response;
    }

    /**
     * 门诊缴费确认 -外部接口 yyt.clinic.mzfee.pay.ack
     * 
     * @param data
     * @param sessionId
     * @param appId
     * @return
     * @throws Exception
     */
    public Response ackMzfeePay(String data, String sessionId, String appId) throws Exception {
        Response response = new Response();
        OrderExtVo order = JsonUtils.parseObject(data, OrderExtVo.class);
        // 查询就诊卡的门诊订单有没有异常
        Map<String, Object> queryMap = new HashedMap();
        queryMap.put("medical_card_no", order.getMedicalCardNo());
        queryMap.put("order_status", OrderExtVo.ORDER_STATUS_EXCEPTION);
        Response ordResponse = BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.list",
                JsonUtils.toJsonString(queryMap));

        logger.info("ackMzfeePay, yyt.base.order.list ordResponse=" + JSON.toJSONString(ordResponse));
        if (!"0".equals(ordResponse.getResultCode())) {
            response.setResultCodeAndMessage("3000", "查询订单失败。");
            return response;
        }

        List expList = JsonUtils.parseObject(ordResponse.getResult(), List.class);
        if (expList != null && expList.size() > 0) {
            response.setResultCodeAndMessage("3000", "存在异常单，请先到缴费记录处理异常订单");
            return response;
        }

        Map<String, String> dataMap = new HashMap<String, String>();
        dataMap.put("order_no", order.getOrderNo());
        logger.info("listMzfeeOut, yyt.base.order.by.order.no.out.get request=" + JSON.toJSONString(dataMap));
        ordResponse = BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.by.order.no.out.get",
                JsonUtils.toJsonString(dataMap));
        logger.info("listMzfeeOut, yyt.base.order.by.order.no.out.get ordResponse=" + JSON.toJSONString(ordResponse));
        if (!"0".equals(ordResponse.getResultCode())) {
            response.setResultCodeAndMessage("3000", "查询订单失败。");
            return response;
        }

        order = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);

        // 门诊缴费确认
        AckClinicPayVo ackClinicPayVo = new AckClinicPayVo();
        String extraParams = order.getExtraParams();
        JSONObject jsonObject = JSON.parseObject(extraParams);
        ackClinicPayVo.setMzFeeId(jsonObject.getString("mz_fee_id"));
        ackClinicPayVo.setPatCardNo(order.getMedicalCardNo());
        ackClinicPayVo.setPatCardType(String.valueOf(order.getMedicalCardType()));
        ackClinicPayVo.setHospitalCode(order.getOrgCode());
        ResCommon<AckClinicPayVoResponse> resCommon = HisifaceService.getHisifaceClient().ackClinicPay(ackClinicPayVo);
        logger.info("ackMzfeePay ackClinicPay,request:{},response:{}", JSON.toJSONString(ackClinicPayVo),
                JSON.toJSONString(resCommon));
        if (!"0".equals(resCommon.getResultCode())) {
            response.setResultCodeAndMessage("3000", "调用门诊缴费确认接口失败:" + resCommon.getResultMessage() + "！");
            return response;
        }
        AckClinicPayVoResponse ackClinicPayVoResponse = resCommon.getResult();
        if (ackClinicPayVoResponse != null) {
            order.setHisOrderNo(ackClinicPayVoResponse.getHisOrdNum());
            order.setTotalAmount(ObjectParser.toInteger(ackClinicPayVoResponse.getTotalAmount()));
            order.setPayAmount(ObjectParser.toInteger(ackClinicPayVoResponse.getPayAmount()));
        } else {
            response.setResultCodeAndMessage("3000", "查询his门诊缴费确认返回空！");
            return response;
        }

        // 生成订单，保存数据库
        try {
            logger.info("ackMzfeePay-> update=" + JSON.toJSONString(order));

            BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.update", JsonUtils.toJsonString(order));

        } catch (Exception ex) {
            logger.error("ackMzfeePay-> 更新订单失败!", ex);
            throw new CallException("3000", "ackMzfeePay-> 更新订单失败!", ex);
        }

        response.setResult(JSON.toJSONString(order));
        response.setResultCodeAndMessage("0", "生成订单成功");
        // order.setId(PKGenerator.generateId());
        // order.setHisOrderNo(CacheService.generateOrderNum(2, 1));

        return response;
    }

    /**
     * yyt.clinic.mzfee.selfpay.get 用户选了医保再切回自费支付时，需要重新获取自费信息，如自费金额等。
     */
    public Response getMzfeeSelfpay(String json, String sessionId) {
        logger.info("刷新自费金额, 方法入参data=" + json + ", sessionId=" + sessionId);
        ClinicVo requestVo = JsonUtils.parseObject(json, ClinicVo.class);
        Response response = new Response();
        Map<String, String> dataMap = new HashMap<String, String>();
        dataMap.put("order_no", requestVo.getPsOrdnum());
        logger.info(
                "刷新自费金额, 订单号" + requestVo.getPsOrdnum() + ", 调base模块, 查询订单接口入参request=" + JSON.toJSONString(dataMap));
        Response ordResponse = BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.by.order.no.out.get",
                JsonUtils.toJsonString(dataMap));
        logger.info("刷新自费金额, 订单号" + requestVo.getPsOrdnum() + ", 调base模块, 查询订单接口返回response="
                + JSON.toJSONString(ordResponse));
        if (!"0".equals(ordResponse.getResultCode())) {
            response.setResultCodeAndMessage("3000", "查询订单失败。");
            return response;
        }
        OrderExtVo order = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);
        JSONObject extraParamsMap = JsonUtils.parseObject(order.getExtraParams());
        String selfpayInfo = extraParamsMap.getString("selfpay_info");
        logger.info("刷新自费金额, 订单号" + requestVo.getPsOrdnum() + ", 自费信息info=" + selfpayInfo);
        if (StringUtils.isNotBlank(selfpayInfo)) {
            JSONObject selfpayMap = JsonUtils.parseObject(selfpayInfo);
            order.setPayAmount(ObjectParser.toInteger(selfpayMap.getString("pay_amount")));
            order.setPayRealAmount(ObjectParser.toInteger(selfpayMap.getString("pay_real_amount")));
            order.setAccountAmount(ObjectParser.toInteger(selfpayMap.getString("account_amount")));
            order.setMedicareAmount(ObjectParser.toInteger(selfpayMap.getString("medicare_amount")));
            order.setInsuranceAmount(ObjectParser.toInteger(selfpayMap.getString("insurance_amount")));
            order.setTotalAmount(ObjectParser.toInteger(selfpayMap.getString("total_amount")));

            logger.info("刷新自费金额, 订单号" + requestVo.getPsOrdnum() + ", 调base模块, 更新订单状态入参request="
                    + JSONObject.toJSONString(order));
            BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.update", JsonUtils.toJsonString(order));
        }
        return response;
    }

    /**
     * 门诊缴费划价-- yyt.clinic.mzfee.price
     * @return
     */
    public Response priceMzfee(String data, String sessionId, String appId){
        Response response = new Response();
        logger.info("门诊缴费划价--->data:" + data );
        Map<String,Object> requestVo = JsonUtils.parseObject(data, Map.class);
        String orderNo = (String) requestVo.get("order_no");
        String payMode = requestVo.get("pay_mode")==null?"0": (String) requestVo.get("pay_mode");

        if(StringUtils.isBlank(orderNo)){
            response.setResultCodeAndMessage("-1","订单号不能为空");
        }

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("order_no", orderNo);
        dataMap.put("order_type", OrderExtVo.ORDER_TYPE_CLINIC);
        Response ordResponse = BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.by.orderno.get",
                JsonUtils.toJsonString(dataMap));
        if (!"0".equals(ordResponse.getResultCode())) {
            logger.error("priceMzfee, yyt.base.order.by.orderno.get ordResponse=" + JSON.toJSONString(ordResponse));
            response.setResultCodeAndMessage(ordResponse.getResultCode(), ordResponse.getResultMessage());
            return response;
        }
        OrderExtVo order = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);

        if(order == null){
            response.setResultCodeAndMessage("3002", "订单不存在。");
            return response;
        }

        //广中医药调用划价接口
        ClinicPrePriceVo clinicPrePriceVo = new ClinicPrePriceVo();
        clinicPrePriceVo.setHospitalCode(order.getOrgCode());
        clinicPrePriceVo.setBranchCode(order.getBranchCode());
        clinicPrePriceVo.setPatCardNo(order.getMedicalCardNo());
        clinicPrePriceVo.setPatCardType(String.valueOf(order.getMedicalCardType()));
        clinicPrePriceVo.setYytOrdNum(order.getOrderNo());
        clinicPrePriceVo.setPayMode(payMode);
        Map<String, String> extraParamsMap = JsonUtils.parseObject(order.getExtraParams(),Map.class);
        clinicPrePriceVo.setMzFeeId(extraParamsMap.get("mz_fee_id"));

        ResCommon<ClinicPrePriceVoResponse> hisPriceResponse = HisifaceService.getHisifaceClient().getClinicPrePrice(clinicPrePriceVo);
        logger.info("待缴费查询外部接口,划价 call hisiface getClinicPrePrice,request={},response={}" ,
                JsonUtils.toJsonString(clinicPrePriceVo),JsonUtils.toJsonString(hisPriceResponse));
        if(!"0".equals(hisPriceResponse.getResultCode())){
            response.setResultCodeAndMessage(hisPriceResponse.getResultCode(),"调用划价接口异常，请稍后再试");
            return response;
        }else{
            ClinicPrePriceVoResponse prePriceResponse = JsonUtils.parseObject(hisPriceResponse.getResult(), ClinicPrePriceVoResponse.class);
            if(prePriceResponse != null) {
                order.setPayAmount(ObjectParser.toInteger(prePriceResponse.getPayAmount()));
                order.setTotalAmount(ObjectParser.toInteger(prePriceResponse.getTotalAmount()));

                BaseService.callUnderlineFromInternal("",
                        "yyt.base.order.update", JsonUtils.toJsonString(order));
                Map<String,String> map = new HashedMap();
                map.put("pay_amount",prePriceResponse.getPayAmount());
                map.put("total_amount",prePriceResponse.getTotalAmount());
                response.setResult(JsonUtils.toJsonString(map));
                response.setResultCodeAndMessage("0","划价成功，支付金额更改为" + prePriceResponse.getPayAmount());
            }else{
                response.setResultCodeAndMessage(hisPriceResponse.getResultCode(),"调用划价接口异常，请稍后再试");
                return response;
            }
        }

        return  response;
    }

    /**
     * 上传处方明细
     * @param data
     * @interface yyt.clinic.mzfee.prescription.upload
     * @return
     */
    public Response uploadMzfeePrescription(String data, String sessionId){
        logger.info("【clinic模块-上传处方明细】开始, 请求="+data,",sessionId=" + sessionId);
        Response response = new Response();

        PrescriptionUploadVo prescriptionUploadVo = JsonUtils.parseObject(data, PrescriptionUploadVo.class);

        //参数校验
        if(prescriptionUploadVo == null){
            response.setResultCodeAndMessage("3000","用上传处方明细接口失败：参数空");
            logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
            return response;
        }else if(StringUtils.isBlank(prescriptionUploadVo.getPatCardNo())){
            response.setResultCodeAndMessage("3000","pat_card_no不能为空");
            logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
            return response;
        }else if(StringUtils.isBlank(prescriptionUploadVo.getPatCardType())){
            response.setResultCodeAndMessage("3000","pat_card_type不能为空");
            logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
            return response;
        }else if(StringUtils.isBlank(prescriptionUploadVo.getMzFeeId())){
            response.setResultCodeAndMessage("3000","mz_fee_id不能为空");
            logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
            return response;
        }else if(StringUtils.isBlank(prescriptionUploadVo.getMzBillId())){
            response.setResultCodeAndMessage("3000","mz_bill_id不能为空");
            logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
            return response;
        }else if(StringUtils.isBlank(prescriptionUploadVo.getDeptCode())){
            response.setResultCodeAndMessage("3000","dept_code不能为空");
            logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
            return response;
        }else if(StringUtils.isBlank(prescriptionUploadVo.getDoctorCode())){
            response.setResultCodeAndMessage("3000","doctor_code不能为空");
            logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
            return response;
        }

        ResCommon<PrescriptionUploadVoResponse> prescriptionUploadVoResponse = HisifaceService.getHisifaceClient().prescriptionUpload(prescriptionUploadVo);
        logger.info("【clinic模块-上传处方明细-调用prescriptionUpload接口】,request={},response={}" ,
                JsonUtils.toJsonString(prescriptionUploadVo),JsonUtils.toJsonString(prescriptionUploadVoResponse));

        if(!"0".equals(prescriptionUploadVoResponse.getResultCode())){
            response.setResultCodeAndMessageAndResult("3000",prescriptionUploadVoResponse.getResultMessage(),JsonUtils.toJsonString(prescriptionUploadVoResponse.getResult()));
        }else{
            response.setResultCodeAndMessageAndResult("0","调用上传处方明细接口成功",JsonUtils.toJsonString(prescriptionUploadVoResponse.getResult()));
        }

        logger.info("【clinic模块-上传处方明细】结束, 返回结果=" + JsonUtils.toJsonString(response));
        return response;
    }

    /**
     * 发送门诊缴费成功短信-- yyt.clinic.mzfee.sms.send
     * @return
     */
    public Response sendMzfeeSms(String data, String sessionId, String appId){
        Response response = new Response();
        logger.info("发送门诊缴费成功短信--->data:" + data );
        Map<String,Object> requestVo = JsonUtils.parseObject(data, Map.class);
        String orderNo = (String) requestVo.get("order_no");

        if(StringUtils.isBlank(orderNo)){
            response.setResultCodeAndMessage("-1","订单号不能为空");
        }

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("order_no", orderNo);
        dataMap.put("order_type", OrderExtVo.ORDER_TYPE_CLINIC);
        Response ordResponse = BaseService.callUnderlineFromInternal(sessionId, "yyt.base.order.by.orderno.get",
                JsonUtils.toJsonString(dataMap));
        if (!"0".equals(ordResponse.getResultCode())) {
            logger.error("priceMzfee, yyt.base.order.by.orderno.get ordResponse=" + JSON.toJSONString(ordResponse));
            response.setResultCodeAndMessage(ordResponse.getResultCode(), ordResponse.getResultMessage());
            return response;
        }
        OrderExtVo order = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);

        if(order == null){
            response.setResultCodeAndMessage("3002", "订单不存在。");
            return response;
        }

        Map<String,Object> smsMap = new HashedMap();
        smsMap.put("org_code",order.getOrgCode());
        smsMap.put("to_user",(requestVo.get("mobile") == null || StringUtils.isBlank((String) requestVo.get("mobile")))?order.getUserMobile():requestVo.get("mobile"));
        smsMap.put("template_code","sms_clinic_001");
        smsMap.put("platform_org_app_code",order.getPlatformOrgAppCode());
        Map<String,String> contentMap = JsonUtils.parseObject(JsonUtils.toJsonString(order),Map.class);
        contentMap.putAll(JsonUtils.parseObject(order.getExtraParams(),Map.class));
        contentMap.put("pay_time",order.getPayTime());
        smsMap.put("msg_content",contentMap);

        Response messageResponse = MessageService.callHumpFromInternal("yyt.message.msg.sms.send",JsonUtils.toJsonString(smsMap));
        logger.info("订单号" + order.getOrderNo() + ", 调用message模块,yyt.message.msg.sms.send request={}，response={}",
                JsonUtils.toJsonString(smsMap),JsonUtils.toJsonString(messageResponse));

        return  messageResponse;
    }
}
